#pragma once
#include "Acceptor.h"
#include "TcpConnection.h"

#include <sys/epoll.h>

#include <vector>
#include <map>
#include <memory>
#include <mutex>

using std::vector;
using std::map;
using std::shared_ptr;
using std::mutex;

class TcpConnection;
class EventLoop
{
public:
    using TcpConnectionPtr = shared_ptr<TcpConnection>;
    using TcpConnectionCallback = function<void(const TcpConnectionPtr &)>;
    using Functor = function<void()>;

    EventLoop(Acceptor &acceptor);
    ~EventLoop();
    void loop();
    void unloop();

    void setNewConnectionCallback(TcpConnectionCallback &&cb);
    void setMessageCallback(TcpConnectionCallback &&cb);
    void setCloseCallback(TcpConnectionCallback &&cb);

private:
    int createEpollFd();
    void addEpollReadFd(int fd);
    void delEpollReadFd(int fd);
    void waitEpollFd();
    void handleNewConnection();
    void handleMessage(int fd);

private:
    int createEventFd();
    void handleRead(); // 内核计数清0
    void doPengdingFunctors();

public:
    void wakeup();
    void runInLoop(Functor &&cb); // 由TcpConnection执行任务添加和通知

private:
    int _epollfd;
    vector<epoll_event> _evtList;
    Acceptor &_acceptor;
    bool _isLooping;

    map<int, TcpConnectionPtr> _conns; // fd -> &conn

    TcpConnectionCallback _onNewConnection;
    TcpConnectionCallback _onMessage;
    TcpConnectionCallback _onClose;

    int _wakefd;               // event_fd 任务通知
    vector<Functor> _pendings; // 待执行的任务队列
    mutex _mutex;              // 互斥访问pendings队列
};
